#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member

using System;
using System.Threading;
using System.Threading.Tasks;

namespace EntityKit.Runtime
{
    /// <summary>
    /// Task 扩展方法
    /// </summary>
    public static class TaskExtensions
    {
        /// <summary>
        /// 忽略Task的异常，防止出现未观察的异常
        /// </summary>
        /// <param name="task">Task</param>
        public static async void Forget(this Task task)
        {
            try
            {
                await task;
            }
            catch
            {
                // 忽略异常
            }
        }
        
        /// <summary>
        /// 带有超时控制的Task执行
        /// </summary>
        /// <param name="task">要执行的Task</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <typeparam name="T">Task返回值类型</typeparam>
        /// <returns>Task的返回值，如果超时则抛出TimeoutException</returns>
        public static async Task<T> WithTimeout<T>(this Task<T> task, int timeout)
        {
            using (var cts = new CancellationTokenSource())
            {
                cts.CancelAfter(timeout);
                var completedTask = await Task.WhenAny(task, Task.Delay(timeout, cts.Token));
                if (completedTask == task)
                {
                    cts.Cancel();
                    return await task;
                }
                else
                {
                    throw new TimeoutException($"Task timed out after {timeout} milliseconds");
                }
            }
        }
        
        /// <summary>
        /// 带有超时控制的Task执行
        /// </summary>
        /// <param name="task">要执行的Task</param>
        /// <param name="timeout">超时时间</param>
        /// <returns>如果超时则抛出TimeoutException</returns>
        public static async Task WithTimeout(this Task task, System.TimeSpan timeout)
        {
            using (var cts = new CancellationTokenSource())
            {
                cts.CancelAfter(timeout);
                var completedTask = await Task.WhenAny(task, Task.Delay(timeout, cts.Token));
                if (completedTask == task)
                {
                    cts.Cancel();
                    await task;
                }
                else
                {
                    throw new TimeoutException($"Task timed out after {timeout.TotalMilliseconds} milliseconds");
                }
            }
        }
        
        /// <summary>
        /// 将Task包装为可安全等待的形式，即使被取消也不会抛出异常
        /// </summary>
        /// <param name="task">要包装的Task</param>
        /// <returns>安全的Task</returns>
        public static async Task SafeAwait(this Task task)
        {
            try
            {
                await task;
            }
            catch (System.OperationCanceledException)
            {
                // 忽略取消异常
            }
        }
    }
}